﻿using System;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using DICOMViewer.UC;
using Leadtools.Dicom;
using qiniu_class.Storage;

namespace DICOMViewer.Utility
{
    public class ImageConverter
    {
        /// <summary>
        ///     后台线程调用worker
        /// </summary>
        private readonly BackgroundWorker converter = new BackgroundWorker();

        private readonly int fileCount;
        private readonly string[] filePathAry;
        private readonly string orderNumber;

        /// <summary>
        ///     构造函数
        /// </summary>
        /// <param name="filePathAry">需要压缩的DICOM文件路径数组</param>
        /// <param name="orderNumber">保存文件的路径（一般为应用程序下temp文件夹下）</param>
        /// <param name="progressForm"></param>
        public ImageConverter(string[] filePathAry, string orderNumber, ProgressForm progressForm) : this()
        {
            this.filePathAry = filePathAry;

            fileCount = filePathAry.Length;
            this.orderNumber = orderNumber;
            this.progressForm = progressForm;
            this.progressForm.progressCounter.Maximum = fileCount;
        }

        /// <summary>
        ///     基础初始化函数，内含backgroundworker的设置
        /// </summary>
        protected ImageConverter()
        {
            converter.WorkerReportsProgress = true;
            converter.DoWork += Converter_DoWork;
            converter.ProgressChanged += Converter_ProgressChanged;
            converter.RunWorkerCompleted += Converter_RunWorkerCompleted;
        }

        /// <summary>
        ///     相关的进度条窗口
        /// </summary>
        public ProgressForm progressForm { get; set; }

        /// <summary>
        ///     将DICOM图像按照Jpeg2000格式压缩。
        /// </summary>
        /// <param name="ds"></param>
        public static void ConvertJpeg2000(DicomDataSet ds)
        {
            try
            {
                DicomJpeg2000Options options = ds.DefaultJpeg2000Options;
                options.CompressionControl = DicomJpeg2000CompressionControl.Lossless;
                Console.WriteLine(
                    "Changed CompressionControl to DicomJpeg2000CompressionControl.Ratio and DicomJpeg2000CompressionControl.CompressionRatio to 50");
                //相关文档参见：https://www.leadtools.com/help/leadtools/v19/dh/di/dicomdataset-setimage.html
                ds.Jpeg2000Options = options;
                ds.ChangeTransferSyntax(DicomUidType.JPEG2000, 2, ChangeTransferSyntaxFlags.None);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        public event EventHandler BeforeConvert;

        /// <summary>
        ///     压缩完成事件，对外公布
        /// </summary>
        public event RunWorkerCompletedEventHandler OnConverCompleted
        {
            add { converter.RunWorkerCompleted += value; }
            remove { converter.RunWorkerCompleted -= value; }
        }

        /// <summary>
        ///     压缩启动函数，会启动压缩的异步时间并弹出进度条窗口
        /// </summary>
        public void beginConvert()
        {
            BeforeConvert?.Invoke(null, null);
            converter.RunWorkerAsync();
        }

        private void Converter_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            progressForm.DialogResult = DialogResult.OK;
            progressForm.Dispose();
        }

        private void Converter_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressForm.Invoke(new EventHandler((a, b) =>
            {
                progressForm.progressCounter.Value = e.ProgressPercentage;
                progressForm.counterLabel.Text = string.Format("正在压缩图像... ( {0} % )",
                    e.ProgressPercentage*100/progressForm.progressCounter.Maximum);
            }));
        }

        private void Converter_DoWork(object sender, DoWorkEventArgs e)
        {
            var savePath = Application.StartupPath + "\\temp\\" + orderNumber + "_dicom.zip";
            //初始化ZipEx类
            ZipEx ziper = new ZipEx();
            ziper.InitZip(savePath);
            for (var i = 0; i < filePathAry.Length; i++)
            {
                //跳过DICOMDIR文件
                if (!filePathAry[i].EndsWith("DICOMDIR"))
                {
                    //打开文件并开始使用jpeg2000保存
                    DicomDataSet ds = new DicomDataSet();
                    ds.Load(filePathAry[i], DicomDataSetLoadFlags.None);
                    try
                    {
                        DicomElement InsititusionNameInformation;
                        DicomElement patientInformation;

                        // 脱敏操作
                        patientInformation = ds.FindFirstElement(null, DicomTag.PatientName, false);
                        if (patientInformation != null)
                            ds.SetStringValue(patientInformation, orderNumber);
                        patientInformation = ds.FindFirstElement(null, DicomTag.PatientAge, false);
                        if (patientInformation != null)
                            ds.SetAgeValue(patientInformation,
                                new[] {new DicomAgeValue {Number = 100, Reference = DicomAgeReferenceType.Years}});
                        patientInformation = ds.FindFirstElement(null, DicomTag.PatientBirthDate, false);
                        if (patientInformation != null)
                            ds.SetDateValue(patientInformation, new DicomDateValue {Day = 1, Month = 1, Year = 1900});
                        InsititusionNameInformation = ds.FindFirstElement(null, DicomTag.InstitutionName, false);
                        if (patientInformation != null)
                            ds.SetStringValue(InsititusionNameInformation, "******");
                    }
                    catch (Exception exception)
                    {
                    }
                    ConvertJpeg2000(ds);
                    MemoryStream mstream = new MemoryStream();
                    //将使用J2k转压的数据保存在内存流中
                    ds.Save(mstream, DicomDataSetSaveFlags.None);
                    //将文件的内存流保存到Zip流
                    ziper.AppendZipFile(mstream, filePathAry[i]);
                    ds.Dispose();
                }
                //通报进展，引发ProgressChanged事件
                converter.ReportProgress(i);
            }
            //输出成Zip文件
            ziper.OutPut();
        }
    }
}